using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.ComponentModel;
using System.Web.UI.Design;

using PHSRAG.Insight21.ClinicalTrials;

namespace PHSRAG.Insight21.InsightWebControls.ClinicalTrials
{
    /// <summary>
    /// The Budget Staff List Control is used as a container for all BudgetStaff  controls.  
    /// It also contains buttons for action on the contained controls
    /// </summary>
    [ToolboxData("<{0}:BudgetStaffListControl runat=server></{0}:BudgetStaffListControl>"), Designer(typeof(BudgetStaffListControlDesigner))]
    public class BudgetStaffListControl : System.Web.UI.Control, INamingContainer
    {
        #region Instance Variables
        private Budget budget;
        private ArrayList budgetStaffControls = new ArrayList();
        private Button addMoreRoles;
        private Button saveStaffing;
        private Button deleteRoles;
        private ValidationSummary validationSummary;
        #endregion

        #region Constants
        private const int addStaffControlOffset = 1;
        private const string naPerson = "N/A";
        #endregion

        #region public properties
        public string SaveButtonClientId
        {
            get { EnsureChildControls(); return saveStaffing.ClientID; }
        }

        public string DeleteRolesButtonClientId
        {
            get { EnsureChildControls(); return deleteRoles.ClientID; }
        }
        #endregion

        #region Overrides
        /// <summary>
        /// Runs upon loading of the control
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            EnsureChildControls();
        }

        /// <summary>
        /// Called by EnsureChildControls to add all child controls to the control tree.
        /// </summary>
        protected override void CreateChildControls()
        {
            budget = (Budget)((Policy.ICachePolicy)Page.Session[Policy.Names.CachePolicyKey]).GetCachedObject(Budget.CacheKey);
            CreateControls();
            GenerateControlTree();
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Creates the actual controls, applying styles, setting values and binding validation.
        /// </summary>
        private void CreateControls()
        {
            validationSummary = new ValidationSummary();
            validationSummary.HeaderText = "The following errors have occurred.";
            validationSummary.ShowSummary = true;

            BudgetStaffList budgetStaffList = budget.BudgetStaff;
            // For each budget staff object, create a control and add it to the arraylist
            int numberOfBudgetStaff = budgetStaffList.Count;
            for (int i = 0; i < numberOfBudgetStaff; ++i)
            {
                BudgetStaffControl newControl = new BudgetStaffControl(budgetStaffList[i]);
                newControl.ID = string.Format("budgetStaff{0}", i);
                budgetStaffControls.Add(newControl);
            }

            // Setup buttons
            addMoreRoles = new Button();
            addMoreRoles.ID = "addMoreRoles";
            addMoreRoles.CssClass = "Button";
            addMoreRoles.Text = "Add More Roles";
            addMoreRoles.Click += new EventHandler(OnAddMoreRoles);
            saveStaffing = new Button();
            saveStaffing.ID = "saveStaffing";
            saveStaffing.CssClass = "Button";
            saveStaffing.Text = "Save Staffing";
            saveStaffing.Click += new EventHandler(OnSaveStaffing);
            deleteRoles = new Button();
            deleteRoles.ID = "deleteRoles";
            deleteRoles.CssClass = "Button";
            deleteRoles.Text = "Delete Roles";
            deleteRoles.Click += new EventHandler(OnDeleteRoles);
        }

        /// <summary>
        /// Adds the controls to the control tree
        /// </summary>
        private void GenerateControlTree()
        {
            Controls.Add(validationSummary);

            Controls.Add(new LiteralControl(
               "<table width=\"100%\" style=\"height: 5px; background-color:#5a76a0; color:White; font-weight:bold\">\n" +
               "<tr><td>Budget Staffing</td></tr></table>" +
               "<table width=\"100%\" class=\"DataGrid\">\n" +
               "\t<tr class=\"DataGridHeader\">\n" +
               "\t\t<td style=\"width:60%\">Role</td>\n" +
               "\t\t<td style=\"width:20%\">Rate Per Hour</td>\n" +
               "\t\t<td style=\"width:10%\">Total Hours</td>\n" +
               "\t\t<td style=\"width:10%\">Delete</td>\n" +
               "\t</tr>"));
            foreach (BudgetStaffControl budgetStaffControl in budgetStaffControls)
            {
                if (!budgetStaffControl.IsNAPerson)
                    Controls.Add(budgetStaffControl);
            }

            Controls.Add(new LiteralControl(
               "<tr><td colspan=\"4\">" ) );

            Controls.Add(addMoreRoles);
            Controls.Add(new LiteralControl("&nbsp;"));
            Controls.Add(saveStaffing);
            Controls.Add(new LiteralControl("&nbsp;"));
            Controls.Add(deleteRoles);
            deleteRoles.Attributes.Add("onclick", "return confirm('Are you sure you want to delete the selected role(s)? Doing so will remove all associated tasks.');");

            Controls.Add(new LiteralControl(
               "\t\t</td>\n" +
               "\t</tr>\n" +
               "</table>"));
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Event handler for adding a new role
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAddMoreRoles(object sender, EventArgs e)
        {
            BudgetStaffList budgetStaffList = budget.BudgetStaff;
            BudgetStaff newBudgetStaff = budgetStaffList.CreateNewBudgetStaff();
            BudgetStaffControl newControl = new BudgetStaffControl(newBudgetStaff);
            newControl.ID = string.Format("budgetStaff{0}", ((budgetStaffList.Count - 1) as object));
            Controls.AddAt(Controls.IndexOf(addMoreRoles) - addStaffControlOffset, newControl);
            OnSaveStaffing(sender, e);
        }

        /// <summary>
        /// Event handler for saving budget staff
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void OnSaveStaffing(object sender, EventArgs e)
        {
            // Set the values on each Budget Staff object and save
            BudgetStaffList budgetStaffList = budget.BudgetStaff;
            for (int i = 0; i < budgetStaffList.Count; ++i)
            {
                BudgetStaff budgetStaff = budgetStaffList[i];
                if (budgetStaff.Id != 0)
                {
                    BudgetStaffControl budgetStaffControl = (BudgetStaffControl)budgetStaffControls[i];
                    if (budgetStaff.StudyStaffRoleCode == "ClinicalTrialBudgetStaffRoleOther")
                    {
                        budgetStaff.OtherRoleText = budgetStaffControl.OtherRoleText;
                    }
                    if (budgetStaff.StudyStaffRoleCode == "ClinicalTrialBudgetStaffRoleNA")
                    {
                        budgetStaff.Rate = budgetStaffList[i].Rate;
                        budgetStaff.StudyStaffRoleMeaning = budgetStaffList[i].StudyStaffRoleMeaning;
                    }
                    else
                    {
                        budgetStaff.Rate = budgetStaffControl.Rate;
                        budgetStaff.StudyStaffRoleMeaning = budgetStaffControl.RoleMeaning;
                    }
                }
                else
                {
                    if (budgetStaffList.Count >= 2)
                    {
                        BudgetStaffControl budgetStaffControl = (BudgetStaffControl)budgetStaffControls[i - 1];

                        budgetStaff.Rate = "300";
                        budgetStaff.StudyStaffRoleMeaning = "PI";
                    }
                }
            }
            if (budgetStaffList.Count >= 2)
                budget.BudgetStaff.Save(Utility.DataAccess.GetConnectionString());
        }

        /// <summary>
        /// Event handler for deleting roles, when a role is deleted so is the task which the 
        /// staff was associated with. Since the role is deleted you cannot have a task 
        /// assigned to a role which no longer exists. 
        /// In addition if the budget id is zero this means we did not complete the role but we do 
        /// want to delete it so we need to remove it from the budget 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnDeleteRoles(object sender, EventArgs e)
        {
            BudgetStaffList budgetStaffList = budget.BudgetStaff;

            int lastItemIndex = budgetStaffList.Count - 1;
            bool mustRefresh = false;

            for (int i = lastItemIndex; i >= 0; --i)
            {
                BudgetStaff budgetStaff = budgetStaffList[i];
                BudgetStaffControl budgetStaffControl = (BudgetStaffControl)budgetStaffControls[i];
                if (budgetStaff.StudyStaffRoleCode != "ClinicalTrialBudgetStaffRoleNA")
                {
                    if (budgetStaffControl.Delete)
                    {
                        if (budgetStaff.Id == 0)
                        {
                            budgetStaffList.RemoveBudgetStaff(budget.BudgetStaff.GetStaffById(0));
                            Controls.RemoveAt(Controls.IndexOf(budgetStaffControl));
                        }
                        else
                        {
                            for (int j = budget.BudgetTasks.Count - 1; j >= 0; --j)
                            {
                                if (budget.BudgetTasks[j].BudgetStaffId == budgetStaff.Id)
                                {
                                    budget.BudgetTasks.RemoveBudgetTask(budget.BudgetTasks[j]);
                                }
                            }
                            budgetStaffList.RemoveBudgetStaff(budgetStaff);
                            mustRefresh = true;
                        }
                    }
                }
            }
            if (mustRefresh)
            {
                budget.Save(Utility.DataAccess.GetConnectionString());
                // Reload the page since controls which we wanted to remove have already been created
                Page.Server.Transfer("BudgetStaffing.aspx");
            }
        }
        #endregion
    }

    #region Class BudgetStaffListControlDesigner
    /// <summary>
    /// Designer associated with the BudgetStaffListControl.
    /// </summary>
    /// <remarks>
    /// This class cannot be used directly.
    /// </remarks>
    public class BudgetStaffListControlDesigner : ControlDesigner
    {
        #region Overrides
        /// <summary>
        /// Since the BudgetStaffListControl does not have any design-time visibility, the designer provides
        /// the type name of that control and the name of the instance.
        /// </summary>
        /// <returns>HTML representation of the BudgetStaffListControl</returns>
        public override string GetDesignTimeHtml()
        {
            return CreatePlaceHolderDesignTimeHtml();
        }
        #endregion
    }
    #endregion
}
